﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.Mvc;
using GigaSite.Domain.Entities;
using GigaSite.Domain.Interfaces.Repositories;
using GigaSite.Domain.IoC;
using GigaSite.Web.Areas.ControlPanel.Exceptions;
using GigaSite.Web.Areas.ControlPanel.Models;

namespace GigaSite.Web.Areas.ControlPanel.Controllers
{
    /// <summary>
    /// Контроллер управления категориями
    /// </summary>
    public class ManageCategoriesController : BaseRootController
    {
        //
        // GET: /ControlPanel/ManageCategories/
        /// <summary>
        /// Контроллер управления категориями
        /// </summary>
        /// <returns></returns>
        public ActionResult Index()
        {
            return View();
        }

        /// <summary>
        /// Загружает древо категорий на клиент
        /// </summary>
        /// <returns>Все категории системы в JSON структуре</returns>
        [HttpPost]
        public JsonResult GetCategories()
        {
            try
            {
                // Перечисляем категории
                var categories = new List<ExtJSTreeNodeModel>();
                EnumerateCategories(-1, categories);

                // Отдаем результат
                return new JsonNetResult()
                           {
                               Data = categories,
                               ContentEncoding = Encoding.UTF8,
                               ContentType = "application/json",
                               JsonRequestBehavior = JsonRequestBehavior.AllowGet
                           };
            }
            catch (Exception e)
            {
                return JsonErrors(e);
            }
        }

        /// <summary>
        /// Рекурсивная функция для построения иерархии объектов в списке
        /// </summary>
        /// <param name="parentId">Идентификатор родительской категории</param>
        /// <param name="categoriesList">Список куда помещать выбранные категории</param>
        private void EnumerateCategories(long parentId, List<ExtJSTreeNodeModel> categoriesList)
        {
            var repository = Locator.GetService<ICategoriesRepository>();
            categoriesList.AddRange(repository.GetChildCategories(parentId).Select(c => new CategoryTreeNodeModel()
                                                                                      {
                                                                                          Expanded = true,
                                                                                          Id = c.Id,
                                                                                          Text = c.DisplayName,
                                                                                          Tooltip = c.Description,
                                                                                          Leaf = false,
                                                                                          Category =
                                                                                              {
                                                                                                  Description =
                                                                                                      c.Description,
                                                                                                  DisplayName =
                                                                                                      c.DisplayName,
                                                                                                  Hidden = c.Hidden,
                                                                                                  SystemName =
                                                                                                      c.SystemName,
                                                                                                  Id = c.Id.ToString(),
                                                                                                  ParentId =
                                                                                                      c.ParentId.
                                                                                                      ToString()
                                                                                              },
                                                                                          Childrens =
                                                                                              new List
                                                                                              <ExtJSTreeNodeModel>()
                                                                                      }));
            foreach (CategoryTreeNodeModel category in categoriesList)
            {
                EnumerateCategories(category.Id,category.Childrens);
            }
        }

        /// <summary>
        /// Сохраняет изменения в узле категории или создает новую категорию с указанными параметрами
        /// </summary>
        /// <param name="id">Идентификатор категории</param>
        /// <param name="parentId">Идентификатор родительской категории</param>
        /// <param name="displayName">Отображаемое имя категории</param>
        /// <param name="systemName">Системное имя категории</param>
        /// <param name="description">Описание категории</param>
        /// <param name="hidden">Отображать ли категорию или нет</param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult Save(long id,long parentId, string displayName,string systemName, string description,bool hidden)
        {
            try
            {
                // Репозиторий
                var repository = Locator.GetService<ICategoriesRepository>();

                // Обрабатываем запрос
                if (id < 0)
                {
                    // Проверяем, существует ли категория с таким же системным именем
                    /*var existedCategory = repository.GetCategoryBySystemName(systemName);
                    if (existedCategory != null)
                    {
                        throw new CategoryExistsException(systemName);
                    }*/

                    // проверяем, существует ли родительская категория, к которой хотят поместить новую категорию
                    if (parentId != -1 && repository.Load(parentId) == null)
                    {
                        throw new CategoryNotExistsException(parentId,
                                                             "Категории, указанная в качестве родительской не существует");
                    }

                    // Создаем категорию
                    var category = new Category()
                                       {
                                           ParentId = parentId,
                                           DisplayName = displayName,
                                           SystemName = systemName,
                                           Description = description,
                                           Hidden = hidden,
                                           DateCreated = DateTime.Now
                                       };
                    repository.Add(category);
                    repository.SubmitChanges();
                    return JsonSuccess(new {id = category.Id});
                }
                else
                {
                    var category = repository.Load(id);
                    category.DisplayName = displayName;
                    category.SystemName = systemName;
                    category.Description = description;
                    category.DateModified = DateTime.Now;
                    category.Hidden = hidden;
                    repository.SubmitChanges();
                    return JsonSuccess(new {id = category.Id});
                }
            }
            catch (Exception e)
            {
                return JsonErrors(e);
            }
        }

        /// <summary>
        /// Удаляет категорию и все в нее вложенные категории
        /// </summary>
        /// <param name="id">Идентификатор категории</param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult Delete(long id)
        {
            try
            {
                // Репозиторий
                var repository = Locator.GetService<ICategoriesRepository>();

                // Проверяем что нам есть что удалять
                var category = repository.Load(id);
                if (category == null)
                {
                    throw new CategoryNotExistsException(id,string.Format("Категория с идентификатором {0} не существует", id));
                }

                // Удаляем
                repository.Delete(category);
                repository.SubmitChanges();

                return JsonSuccess();
            }
            catch (Exception e )
            {
                return JsonErrors(e);
            }
        }

        /// <summary>
        /// Обрабатывает запрос на перемещение категории от одного родителя к другому
        /// </summary>
        /// <param name="id">Идентификатор категории</param>
        /// <param name="newParentId">Идентификатор новой родительской категории</param>
        /// <returns>Информация об успехе или нет</returns>
        [HttpPost]
        public JsonResult Move(long id,long newParentId)
        {
            try
            {
                // Получаем репозиторий
                var repository = Locator.GetService<ICategoriesRepository>();

                // проверяем, существует ли родительская категория, к которой хотят поместить новую категорию
                if (newParentId != -1 && repository.Load(newParentId) == null)
                {
                    throw new CategoryNotExistsException(newParentId,
                                                         "Категории, указанная в качестве родительской не существует");
                }

                // Загружаем категорию
                var category = repository.Load(id);
                if (category == null)
                {
                    throw new CategoryNotExistsException(id,
                                                         "Перемещаемая категория не найдена");
                }

                // Изменяем родителя и сохраняем
                category.ParentId = newParentId;
                repository.SubmitChanges();

                return JsonSuccess();
            }
            catch (Exception e)
            {
                return JsonErrors(e);
            }
        }

    }
}
